Skip to content

Implement env and required struct tag support#12

Merged
phinze merged 5 commits into
mainfrom
phinze/mir-986-add-env-and-required-struct-tag-support-to-mflags
Apr 8, 2026
Merged

Implement env and required struct tag support#12
phinze merged 5 commits into
mainfrom
phinze/mir-986-add-env-and-required-struct-tag-support-to-mflags

Conversation

@phinze

@phinze phinze commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

The runtime CLI has been using env:"VAR_NAME" and required:"true" struct tags on dozens of config fields, but mflags never actually honored either of them. They've been silently ignored this whole time. With MIR-985 adding strict tag validation, upgrading mflags in the runtime repo would surface all of these as errors, so we need to teach mflags what they mean before that upgrade lands.

The env tag populates a flag's default from an environment variable during FromStruct, giving us clean layered precedence: hard-coded default < env var < CLI argument. No changes to Parse were needed since env just acts as a better default that gets overwritten if the user passes the flag explicitly.

The required tag validates after parsing that the flag or positional was actually given a value, either via CLI arg or env var. A HasValue bool on each flag tracks whether it was populated by any source, and validateRequired() runs at the end of Parse to check them all. Missing required flags produce an ErrRequired sentinel so callers can distinguish validation failures from other parse errors.

Both tags work on flags and positionals. Help output now shows (env: VAR_NAME) annotations, and the JSON help doc includes envVar and required fields for tooling consumers.

Closes MIR-986

@phinze phinze requested a review from a team as a code owner April 8, 2026 17:39

@evanphx evanphx left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image

@phinze

phinze commented Apr 8, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Apr 8, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Apr 8, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4b4e0878-7aa1-469f-a220-6d6d9ce1e1f3

📥 Commits

Reviewing files that changed from the base of the PR and between 087ef1f and c790ea4.

📒 Files selected for processing (3)
  • help_doc.go
  • mflags.go
  • mflags_test.go

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.


📝 Walkthrough

Walkthrough

The mflags package adds environment-variable and required-field support. Flag, PositionalField, FlagDoc, and PositionalDoc gain EnvVar and Required (and HasValue on runtime structs). FromStruct recognizes env:"..." and required:"true", applies env values via Value.Set or field setters, and marks values as present. FlagSet tracks required flags/positionals, validates them during Parse() returning ErrRequired for missing items, and help output/doc now show environment-variable annotations. Tests cover env sourcing, overrides, parsing errors, help rendering, and required enforcement.


Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
mflags.go (1)

1821-1823: Document env and required in FromStruct's public tag list.

These tags are now part of the exported surface, but the FromStruct doc comment still omits them, so generated docs and IDE help are already stale.

Also applies to: 1886-1887

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mflags.go` around lines 1821 - 1823, Update the public doc comment for the
FromStruct function to include the newly supported "env" and "required" struct
tag keys in its documented tag list (reference: FromStruct), and do the same for
the second FromStruct doc block near the other occurrence; explicitly list "env"
(for environment-variable name) and "required" (boolean "true"/"false") so
generated docs and IDE tooltips reflect the current exported surface.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@mflags.go`:
- Around line 1886-1897: The code currently sets defaultValue and hasEnvValue
when an env var exists, but must instead apply the env string through the flag
implementation and only mark the flag as having a value on successful parsing;
modify the logic around envVar/defaultValue/hasEnvValue so that after
registering the flag (the Flag with its Value implementation) you call
Flag.Value.Set(envVal) (or otherwise use the flag's parse path) and only set
HasValue = true if Set returns nil; for pointer-backed flags, repeatable slices
(e.g., []bool/[]int) and other unsupported kinds, either apply via
Flag.Value.Set or reject the env tag with an error, and make the same fix in the
other occurrence referenced (the block around the second env handling at the
2077-2082 region) so env-backed flags don’t get marked satisfied when parsing
fails.

---

Nitpick comments:
In `@mflags.go`:
- Around line 1821-1823: Update the public doc comment for the FromStruct
function to include the newly supported "env" and "required" struct tag keys in
its documented tag list (reference: FromStruct), and do the same for the second
FromStruct doc block near the other occurrence; explicitly list "env" (for
environment-variable name) and "required" (boolean "true"/"false") so generated
docs and IDE tooltips reflect the current exported surface.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: dfa15ec6-6d92-46b5-9d88-40a20bfacff8

📥 Commits

Reviewing files that changed from the base of the PR and between 8c337ad and 29d5a4f.

📒 Files selected for processing (3)
  • help_doc.go
  • mflags.go
  • mflags_test.go

Comment thread mflags.go Outdated
phinze added 4 commits April 8, 2026 16:03
The runtime CLI has been using env:"VAR_NAME" and required:"true"
struct tags for a while now, but mflags never actually honored them.
They were silently ignored. With strict tag validation coming in
MIR-985, upgrading mflags in the runtime repo would surface these
as errors, so we need to teach mflags what they mean first.

env tags populate a flag's default from an environment variable,
giving us layered precedence: default < env < CLI arg. required
tags validate after parsing that the flag or positional was given
a value (via CLI or env). Both tags work on flags and positionals.

Help output now shows (env: VAR_NAME) annotations, and the JSON
help doc includes envVar and required fields. A new ErrRequired
sentinel lets callers distinguish required-validation failures
from other parse errors.
The env var path for positionals was ignoring the error from
setFieldValue, which would silently swallow parse failures (e.g.
"abc" for an int positional). Now we propagate the error.
The previous approach routed env values through the defaultValue
string, which meant parse errors were silently swallowed and
pointer/slice types never received the value. Now env values are
applied via flag.Value.Set() after registration, which validates
the value and works uniformly across all types.

Also documents env and required tags in FromStruct's doc comment.
After rebasing on MIR-985's strict tag validation, env and required
need to be added to knownTags so FromStruct doesn't reject them.
Updates the test that was asserting they were unknown.
@phinze phinze force-pushed the phinze/mir-986-add-env-and-required-struct-tag-support-to-mflags branch from 087ef1f to cad95e7 Compare April 8, 2026 21:03

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
mflags.go (1)

49-52: setFlags map is populated but never read.

The setFlags map is initialized at line 879 and populated during flag parsing (lines 1541, 1567, 1583, 1592), but it is never read or accessed anywhere in the codebase. If this field is intended for future use, consider adding a clarifying comment. Otherwise, it may be removed as dead code.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mflags.go` around lines 49 - 52, The setFlags map field on the mflags struct
is written during Parse (assignments like setFlags[...] = true) but never read;
either remove the dead field and all assignments that initialize or populate
setFlags, or keep it and add a clarifying comment on the setFlags field (and
consider adding an accessor if external use is intended) so future readers know
it’s intentionally retained; locate the symbol setFlags on the mflags struct and
the assignments in Parse to update accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@mflags.go`:
- Around line 49-52: The setFlags map field on the mflags struct is written
during Parse (assignments like setFlags[...] = true) but never read; either
remove the dead field and all assignments that initialize or populate setFlags,
or keep it and add a clarifying comment on the setFlags field (and consider
adding an accessor if external use is intended) so future readers know it’s
intentionally retained; locate the symbol setFlags on the mflags struct and the
assignments in Parse to update accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1b9e35ad-9c76-4e5b-b2a0-56cfd54ecda9

📥 Commits

Reviewing files that changed from the base of the PR and between 29d5a4f and 087ef1f.

📒 Files selected for processing (2)
  • mflags.go
  • mflags_test.go

Was populated during Parse but never read. The HasValue bool on
Flag handles required validation directly, making this redundant.
@phinze phinze merged commit 1b813c2 into main Apr 8, 2026
1 check passed
@phinze phinze deleted the phinze/mir-986-add-env-and-required-struct-tag-support-to-mflags branch April 8, 2026 21:15
@coderabbitai

coderabbitai Bot commented Apr 8, 2026

Copy link
Copy Markdown

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{}

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
mflags.go (1)

1671-1676: ⚠️ Potential issue | 🟠 Major

Fail fast when a tagged field never registers.

With env and required now treated as recognized tags, an unsupported field like float64 \long:"count" env:"COUNT" required:"true"`` returns nil, registers nothing, ignores the env binding, and skips required validation entirely. Please return an error when a field has flag tags but its kind falls through the registration switch.

Also applies to: 1981-2178

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mflags.go` around lines 1671 - 1676, The code currently adds "env" and
"required" to knownTags but silently ignores fields whose kind falls through the
registration switch (so tagged fields like float64 `long:"count" env:"COUNT"
required:"true"` neither register nor validate); update the field-registration
logic (the function that iterates struct fields and registers flags — e.g., the
registerField / registration switch around lines 1981-2178) to detect when any
of the tags in knownTags are present on a field but no registration branch ran,
and return an explicit error indicating the unhandled kind and tags; implement
this by checking parsed tags (from the existing tag parsing path) and, after the
switch/default path, if no registration occurred and any known tag was set,
return an error describing the field name, type/kind, and the tags so callers
fail fast.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@mflags.go`:
- Around line 49-50: validateRequired currently reads cached slices
requiredFlags and requiredPos (populated only by FromStruct) instead of the live
booleans on Flag and PositionalField, so callers mutating Lookup(...).Required
or GetPositionalFields() are ignored; change validateRequired to consult
Flag.Required and PositionalField.Required directly rather than
requiredFlags/requiredPos, remove or stop using those cached slices where
validation is expected (and update places at the other mentioned regions that
perform required checks to use the .Required booleans), and ensure FromStruct
still sets the .Required fields so both struct-based and programmatic uses are
honored.
- Around line 23-31: The PositionalField struct exposes parser-only fields
Required and HasValue which breaks backwards compatibility for unkeyed struct
literals; change those fields to unexported names (required, hasValue) and keep
them used only internally in the parser (e.g., inside GetPositionalFields and
other parsing logic), and if external callers need their values expose them via
accessors or the existing documentation types (add methods or populate
PositionalDoc/FlagDoc) rather than exported struct fields; update any references
to PositionalField.Required and .HasValue within the package to the new
unexported names and provide public getters or doc generation use where
necessary.

---

Outside diff comments:
In `@mflags.go`:
- Around line 1671-1676: The code currently adds "env" and "required" to
knownTags but silently ignores fields whose kind falls through the registration
switch (so tagged fields like float64 `long:"count" env:"COUNT" required:"true"`
neither register nor validate); update the field-registration logic (the
function that iterates struct fields and registers flags — e.g., the
registerField / registration switch around lines 1981-2178) to detect when any
of the tags in knownTags are present on a field but no registration branch ran,
and return an explicit error indicating the unhandled kind and tags; implement
this by checking parsed tags (from the existing tag parsing path) and, after the
switch/default path, if no registration occurred and any known tag was set,
return an error describing the field name, type/kind, and the tags so callers
fail fast.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cb01d1d0-97a7-40f7-97bc-cfc3becb0d07

📥 Commits

Reviewing files that changed from the base of the PR and between 087ef1f and c790ea4.

📒 Files selected for processing (3)
  • help_doc.go
  • mflags.go
  • mflags_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • help_doc.go
  • mflags_test.go

Comment thread mflags.go
Comment thread mflags.go
@phinze

phinze commented Apr 8, 2026

Copy link
Copy Markdown
Contributor Author

Hey coderabbit, you know the review is supposed to come before the merge, right? We're going to have to get you a watch. 🐰⌚

On the remaining findings: the silent fallthrough for unsupported kinds with env/required tags is a fair point, but this library is pre-1.0 and internal-only so we're not worried about it yet. The FromStruct doc comment nit is noted and we'll pick it up in a future pass.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants